// NodeSpace.h
// think more..
// by Mina Jung @ syracuse university
// April 2010


#import <random.h>
#import "SensorSpace.h"
#import "Sensor.h"
#import "EnvSpot.h"

#import <simtools.h>
#import <misc.h>



@implementation SensorSpace

- createEnd
{
  [super createEnd];

printf("\nSensorSpace -- Create");

  if (Xsize <= 0 || Ysize <= 0)
    [InvalidCombination raiseEvent: "Sensor Space was created with an invalid size\n"];


  environmentGrid = [Grid2d createBegin: [self getZone]];
  [environmentGrid setSizeX: Xsize Y: Ysize];
  environmentGrid = [environmentGrid createEnd];

  EnvironmentValues = [Discrete2d createBegin: [self getZone]];
  [EnvironmentValues setSizeX: Xsize Y: Ysize];
  EnvironmentValues = [EnvironmentValues createEnd];


  sensorGrid = [Grid2d createBegin: [self getZone]];
  [sensorGrid setSizeX: Xsize Y: Ysize];
  sensorGrid = [sensorGrid createEnd];

  return self;
}



//////////////////////////////////////
//
//   size of the world
//
//////////////////////////////////////

- setSizeX: (int) x Y: (int)y
{
  Xsize = x;
  Ysize = y;
  
  return self;
}

- (int)getSizeX
{
  return Xsize;
}

- (int)getSizeY
{
  return Ysize;
}

//////////////////////////////////////
//
//   normalize x-y coordinates
//
//////////////////////////////////////

- (int)xNorm: (int)x
{
  if (x < 0)
    return (x + Xsize*128) % Xsize;
  else if (x >= (int)Xsize)
    return x % Xsize;
  else
    return x;
}

- (int)yNorm: (int)y
{
  if (y < 0)
    return (y + Ysize*128) % Ysize;
  else if (y >= (int)Ysize)
    return y % Ysize;
  else
    return y;
}


//////////////////////////////////////
//
//  manage sensor positions 
//
//////////////////////////////////////

// return the sensor at a particular location
- (Sensor *)getSensorAtX: (int) x Y: (int)y
{
  x = [self xNorm: x];
  y = [self yNorm: y];

  return [sensorGrid getObjectAtX: x Y: y];
}

// add a new sensor to the world..
- addSensor: (Sensor *)sensor atX: (int)x Y: (int)y
{
  EnvSpot *spotHere;


  spotHere = [environmentGrid getObjectAtX: x Y: y];
  [spotHere setSensor];

  x = [self xNorm: x];
  y = [self yNorm: y];

  sensor->x = x;
  sensor->y = y;

  [sensorGrid putObject: sensor atX:x Y: y];

  return self;
}

// remove a sensor from the world
- removeSensor: (Sensor*) sensor
{
  int x, y;

  x = [self xNorm: sensor->x];
  y = [self yNorm: sensor->y];

  if ([self getSensorAtX:x Y: y] == sensor)
    [sensorGrid putObject:nil atX:x Y:y];

  return self;
}

// move a sensor
- moveSesnor: (Sensor *)sensor toX: (int)x Y: (int)y
{

  [self removeSensor: sensor];
  [self addSensor: sensor atX: x Y: y];

  return self;
}


- (id <Grid2d>)getSensorGrid
{
  return sensorGrid;
}
 
  

//////////////////////////////////////
//
//  manage environmental information 
//
//////////////////////////////////////

- initializeEnvironment
{
  int i,j;

printf("\nSensorSpace -- initializeEnvironment");

  for(i = 0; i < Xsize; i++)
  {
    for(j = 0; j < Ysize; j++)
    {
      EnvSpot *spot;

      spot = [EnvSpot createBegin: [self getZone]];
      spot = [spot createEnd];

      [environmentGrid putObject: spot atX:i Y:j];
    }
  }

  return self;
}

- setWallAtX: (int)x Y: (int)y
{
  EnvSpot *spotHere;


  spotHere = [environmentGrid getObjectAtX: x Y: y];
  [spotHere setWall];

  return self;
}

- setEnvironmentRange: (int)a Min: (int)bot Max: (int)top
{
  int i,j;


printf("\nSensorSpace -- setEnvironmentRange type : %d Min: %d Max: %d", a, bot, top);

  for(i = 0; i < Xsize; i++)
  {
    for(j = 0; j < Ysize; j++)
    {
      EnvSpot *spotHere;

      spotHere = [environmentGrid getObjectAtX: i Y: j];
      [spotHere putRange:a Min: bot Max: top];

    }
  }

  return self;

}

- updateEnvironment: (SensedValue)val atX: (int)x Y: (int)y A:(int)a
{
  EnvSpot *spotHere;


  spotHere = [environmentGrid getObjectAtX: x Y: y];
  [spotHere setSpotValue:val type: a];


  return self;
}

 
- (SensedValue)getEnvironmentValueAtX: (int)x Y: (int)y A:(int)a
{
  EnvSpot *spotHere;
  SensedValue value;


  spotHere = [environmentGrid getObjectAtX: x Y: y];

  value = [spotHere getSpotValue: a];


  return value;
}

- updateEnvironmentValues
{
  int i,j, value;

  [EnvironmentValues fillWithValue: 0];

  for(i = 0; i < Xsize; i++)
  {
    for(j = 0; j < Ysize; j++)
    {
      EnvSpot *spotHere;

      spotHere = [environmentGrid getObjectAtX: i Y: j];
      value = [spotHere getEnvValue];

      if(value == -1){
        [EnvironmentValues putValue: 152 atX: i Y: j];
      }
      else if(value > 0){
        [EnvironmentValues putValue: value atX: i Y: j];
      }
    }
  }

  return self;
}


- (id <Discrete2d>)getEnvironmentValues
{
  return EnvironmentValues;
}

@end

